/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	Window.h
*
*	Description -	Used for representing physical windows.
*
*	Comments	-	This is a bit hack implementation. Lots of Win32 specific code here.
*
*	Modification History:
*			Name			   Date					Description
*			MrCodeSushi	-	04/08/2013	-	Creation of this file
**************************************************************************************/
#ifndef _PSX_WINDOW_H_
#define _PSX_WINDOW_H_

#include "PulseSTD.h"
#include "String.h"
#include "Array.h"
#include "WindowView.h"
#include "EventSystem.h"

namespace Pulse
{
	class Window
	{
	public:

		~Window( void );

		const CHAR * GetName( void ) const;

		// Window functionalities
		void Update( const FLOAT dt );

		void Render( void );

		const SIZE_T GetWidth( void ) const { return m_width; }

		const SIZE_T GetHeight( void ) const { return m_height; }

		void Resize( SIZE_T width, SIZE_T height );

		const BOOL IsMainWindow( void ) const { return m_bMainWindow; }

		const BOOL IsSafeToClose( void ) const { return m_bSafeToClose; }

		SwapChain * GetSwapChain( void ) { return m_pSwapChain; }

		const void * GetHandle( void ) const { return m_handle; }
		
		LONG_PTR WindowProc( void *hWnd, UINT msg, WPARAM wParam, LPARAM lParam );

		// TODO: Add WindowView functionalities
		EErrorCode::Type InsertWindowView( WindowView *pView );

		const SIZE_T GetNumWindowViews( void ) const { return m_windowViews.GetSize(); }

		WindowView * FindWindowView( const CHAR *pName );

		EventSystem * GetEventSystem( void ) { return &m_eventSystem; }

	private:

		// Window behavioral methods
		LONG_PTR OnGainFocus( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnLoseFocus( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnSizeMoveEnter( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnSizeMoveExit( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnMove( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnClose( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnQuit( UINT msg, WPARAM wParam, LPARAM lParam );

		LONG_PTR OnDestroy( UINT msg, WPARAM wParam, LPARAM lParam );

	private:

		friend WindowingSystem;

		static EErrorCode::Type Create( const CHAR *pWindowName, Window **ppOut, BOOL bMainWindow = FALSE );

		static void Delete( Window *pWindow );

	private:

		Window( const CHAR *pWindowName );

		Window( const Window &pWindow ); // no-op

		Window & operator = ( const Window &rhs ); // no-op

		EErrorCode::Type Initialize( void );	// Called automatically

		void Cleanup( void );	// Called automatically

	private:

		// Utility Methods
		//////////////////

		void FixWindowSize( void );

		void RemoveAllWindowViews( void );

		// NOTE: Called from WindowSys
		PSX_NO_DIRECT_CALL EErrorCode::Type FromWindowSysRemoveView( const WindowView *pView );

		void UpdateWindowViewSizes( void );

	private:

		// Input system delegates
		//////////////////////////

		void OnKeyUp( IEvent *pEvent );
		
		void OnKeyDown( IEvent *pEvent );
		
		void OnMouseMove( IEvent *pEvent );
		
		void OnMouseButtonUp( IEvent *pEvent );
		
		void OnMouseButtonDown( IEvent *pEvent );

	private:

		typedef Array<WindowView*> WindowViewList;

		String			m_name;
		BOOL			m_bMainWindow;	// The very first window created is the main window
		WindowViewList	m_windowViews;

		INT		m_posX;
		INT		m_posY;
		SIZE_T	m_width;
		SIZE_T	m_height;

		// Behavior variables
		BOOL	m_bMinimized;
		BOOL	m_bWindowed;
		BOOL	m_bClosing;
		BOOL	m_bSafeToClose;

		EventSystem m_eventSystem;

		SwapChain				*m_pSwapChain;
		RenderView				*m_pRenderView;	// For final WindowView's RenderTarget Composition
		RenderEntryRenderTarget *m_pRERenderTarget;
		RenderEntryPresent		*m_pREPresent;
		RenderEntryClearPipeline *m_pREClearPipeline;
		
		// OS specific data
		VOID *m_handle; // Win32 specific HWND
		void *pMsg;		// Used for the messageproc


	};

	PSX_INLINE const CHAR * Window::GetName( void ) const
	{
		return m_name.GetBuffer();
	}
}

#endif /* _PSX_WINDOW_H_ */